package com.lark.web.docker.service;

import com.github.dockerjava.api.command.InspectVolumeResponse;
import com.github.dockerjava.api.command.ListVolumesResponse;
import com.lark.common.utils.DateUtils;
import com.lark.common.utils.StringUtils;
import com.lark.web.domain.Container;
import com.lark.web.domain.Image;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.lark.web.domain.Network;
import com.lark.web.domain.StorageVolume;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Date;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.String.format;

public class DockerUtil {
    private static final Logger log = LoggerFactory.getLogger(DockerUtil.class);
    private static Map<String, DockerClient> dockerClientMap = new ConcurrentHashMap<>();

    /**
     * 创建remote docker客户端
     *
     * @param ip
     * @param port
     * @return
     * @throws URISyntaxException
     */
    public static DockerClient createClient(String ip, String port) {
        // remote docker客户端
        DockerClient dockerClient = DockerClientBuilder.getInstance(format("tcp://%s:%s", ip, port)).build();
        return dockerClient;
    }

    /**
     * 创建local docker客户端
     *
     * @return
     * @throws URISyntaxException
     */
    public static DockerClient createClient() {
        DockerClient dockerClient = DockerClientBuilder.getInstance("unix:///var/run/docker.sock").build();
        return dockerClient;
    }

    /**
     * 查询主机上的镜像
     *
     * @param dockerClient
     * @return
     */
    public static List<Image> getImages(DockerClient dockerClient) {
        List<Image> images = new ArrayList<Image>();
        try {
            List<com.github.dockerjava.api.model.Image> imageList = dockerClient.listImagesCmd().exec();
            imageList.forEach(ig -> {
                Image image = new Image();
                image.setImageId(StringUtils.substring(ig.getId(), 7, 19));
                if (Objects.nonNull(ig.getRepoTags()) || ig.getRepoTags().length > 0) {
                    String[] split = ig.getRepoTags()[0].split(":");
                    image.setImageRepository(split[0]);
                    image.setImageTag(split[1]);
                }
                image.setImageSize(String.valueOf(ig.getSize() / 1000 / 1000)); // M
                image.setImageCreateTime(Date.from(Instant.ofEpochSecond(ig.getCreated())));
                images.add(image);
            });
        } finally {
            try {
                dockerClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return images;
    }

    public static List<StorageVolume> getStorageVolumes(DockerClient dockerClient) {
        List<StorageVolume> storageVolumes = new ArrayList<>();

        ListVolumesResponse response = dockerClient.listVolumesCmd().exec();
        response.getVolumes().forEach(vo -> {
            StorageVolume storageVolume = new StorageVolume();
            storageVolume.setVolumeName(vo.getName());
            storageVolume.setDriver(vo.getDriver());

            InspectVolumeResponse inspectVolumeResponse = dockerClient.inspectVolumeCmd(vo.getName()).exec();
            storageVolume.setScope(String.valueOf(inspectVolumeResponse.getRawValues().get("Scope")));
            storageVolume.setVolumeCreateTime(DateUtils.toDate(String.valueOf(inspectVolumeResponse.getRawValues().get("CreatedAt"))));
            storageVolumes.add(storageVolume);
        });
        return storageVolumes;
    }

    public static List<Network> getNetworks(DockerClient dockerClient) {
        ArrayList<Network> networks = new ArrayList<>();

        List<com.github.dockerjava.api.model.Network> networksResponse = dockerClient.listNetworksCmd().exec();
        networksResponse.forEach(nw -> {
            Network network = new Network();
            network.setNetworkId(StringUtils.substring(nw.getId(), 0, 12));
            network.setNetworkName(nw.getName());
            network.setScope(nw.getScope());
            network.setDirver(nw.getDriver());
            network.setNetworkCreateTime(DateUtils.toDate(String.valueOf(nw.getRawValues().get("Created"))));
            networks.add(network);
        });
        return networks;
    }

    public static List<Container> getContainers(DockerClient dockerClient) {
        ArrayList<Container> containers = new ArrayList<>();

        List<com.github.dockerjava.api.model.Container> containerResponse = dockerClient.listContainersCmd().exec();
        containerResponse.forEach(con -> {
            Container container = new Container();
            container.setContainerId(StringUtils.substring(con.getId(), 0, 12));
            container.setContainerName(con.getNames()[0]);
            container.setContainerCreateTime(DateUtils.toDate(con.getCreated()));
            container.setImage(con.getImage());
            container.setCommand(con.getCommand());
            container.setStatus(con.getStatus());
            containers.add(container);
        });
        return containers;
    }
}
